﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;


public class WindowPrefabAttribute : System.Attribute
{
    public System.Type t;
    public WindowPrefabAttribute(System.Type _t)
    {
        t = _t;
    }
}


public class Window : LuaMonoBehaviour
{
    [HideInInspector]
    public ViewProxy proxy;
    protected UIPanel panel;
    protected UIAnimGroup curChildWinAnim = RootWindowManager.TranslateFadeIn;
    protected UIAnimGroup preChildWinAnim = RootWindowManager.TranslateFadeOut;
    protected UIAnimGroup curWinAnim = RootWindowManager.FadeIn;
    protected UIAnimGroup preWinAnim = RootWindowManager.FadeOut;

    protected WindowManager _parentWinManager = null;
    public WindowManager parentWinManager
    {
        set
        {
            _parentWinManager = value;
        }
        get
        {
            return _parentWinManager;
        }
    }
    protected WindowManager winManager = new WindowManager();

//    private GameObject _tips;
//    private GameObject tips
//    {
//        get
//        {
//            if (_tips == null)
//            {
//                _tips = Instantiate(Resources.Load("Prefab/UI/Tips")) as GameObject;
//                _tips.transform.SetParent(transform, false);
//            }
//            return _tips;
//        }
//    }

    public void setDepth(int depth)
    {
        List<UIPanel> panels = this.GetComponentsInChildrenEx<UIPanel>(true);
        List<Canvas> canvases = this.GetComponentsInChildrenEx<Canvas>(true);

        if(panels.Count > 0)
        {
            panels.Sort((a, b) =>
                {
                    return a.depth - b.depth;
                });

            for (int i = 0; i < panels.Count; i++)
            {
                panels[i].depth = depth + i;
            }

            winManager.startDepth = panels[panels.Count - 1].depth + 1;
            
        }
        else if(canvases.Count > 0)
        {
            if(canvases.Count > 0)
            {

            }
            canvases.Sort((a, b) =>
                {
                    return a.sortingOrder - b.sortingOrder;
                });

            for (int i = 0; i < canvases.Count; i++)
            {
                canvases[i].sortingOrder = depth + i;
            }

            winManager.startDepth = canvases[canvases.Count - 1].sortingOrder + 1;
            
        }
        panels.RecycleToListPool();
        canvases.RecycleToListPool();
    }

	public virtual UIPanel GetPanel()
    {
		if (panel == null)
		{
			panel = this.GetComponent<UIPanel>();
			panel.anchorOffset = true;

			winManager.winParent = this.gameObject;
			winManager.windowDepthCount = 1;
		}
		return panel;
    }

    public virtual void SetParam(Dictionary<string, object> paramMap)
    {
        
    }

//    Renderer[] renders = null;
//    private Renderer[] GetRenders()
//    {
//        if (renders == null)
//        {
//            renders = GetComponentsInChildrenEx<Renderer>();
//        }
//        return renders;
//    }

    private UITweener createTween(GameObject obj, IUIAnimElem animInfo, UIAnimElem elem, bool forward)
    {
        switch (elem.type)
        {
            case WindowAnimType.Alpha:
            {
                    TweenAlpha alphaTween = TweenAlpha.Begin(obj, elem.duration <= 0? animInfo.duration: elem.duration, elem.to);
                    alphaTween.from = elem.from;
                    alphaTween.method = elem.method;
                    alphaTween.Play(forward);
                    alphaTween.ResetToBeginning();
                return alphaTween;
            }
            case WindowAnimType.Scale:
            {
                    TweenScale tween = TweenScale.Begin(this.gameObject, elem.duration <= 0? animInfo.duration: elem.duration, new Vector3(elem.to, elem.to, 1));
                    tween.from = new Vector3(elem.from, elem.from, 1);
                    tween.method = elem.method;
                    tween.Play(forward);
                    tween.ResetToBeginning();
                    return tween;
            }
            case WindowAnimType.Rotation:
                {
                    TweenRotation tween = TweenRotation.Begin(this.gameObject, elem.duration <= 0? animInfo.duration: elem.duration, Quaternion.identity);
                    tween.from = new Vector3(0, 0, elem.from);
                    tween.to = new Vector3(0, 0, elem.to);
                    tween.method = elem.method;
                    tween.Play(forward);
                    tween.ResetToBeginning();
                    return tween;
                }
            case WindowAnimType.Translate:
                {
                    TweenPosition tween = TweenPosition.Begin(this.gameObject, elem.duration <= 0? animInfo.duration: elem.duration, Vector3.zero, false);
					Vector2 s = GetPanel().GetWindowSize();
                    tween.from = new Vector3(elem.vFrom.x * s.x, elem.vFrom.y * s.y, 0);
                    tween.to = new Vector3(elem.vTo.x * s.x, elem.vTo.y * s.y, 0);
                    tween.method = elem.method;
                    tween.Play(forward);
                    tween.ResetToBeginning();
                    return tween;
                }
            default:
                return null;
        }
    }

    public void SetAnim(IUIAnimElem animElem, bool forward, System.Action callBack)
    {
        if (animElem != null)
        {
            if (animElem is UIAnimElem)
            {
                
            }
            else
            {
                UIAnimGroup animGroup = animElem as UIAnimGroup;
                UITweener maxTimeTween = null;
                for (int i = 0; i < animGroup.anims.Count; i++)
                {
                    UIAnimElem elem = animGroup.anims[i];
                    UITweener tweener = createTween(this.gameObject, animGroup, elem, forward);

                    List<Renderer> renders = this.GetComponentsInChildrenEx<Renderer>();
                    for(int j = 0; j < renders.Count; j++)
                    {
                        Material mat = renders[j].sharedMaterial;
                        if(mat != null && mat.HasProperty("_Color"))
                        {
                            createTween(renders[j].gameObject, animGroup, elem, forward);
                        }
                    }

                    if (maxTimeTween == null || tweener.duration > maxTimeTween.duration)
                    {
                        maxTimeTween = tweener;
                    }
                }

                if (callBack != null && maxTimeTween != null)
                {
                    maxTimeTween.SetOnFinished(() =>
                        {
                            callBack();
                        });
                }
            }
        }
    }

    public void Close()
    {
        bool forward = false;
        IUIAnimElem anim = this.proxy.GetCloseAnim(out forward);
        Close(anim, forward);
    }

    public void Close(IUIAnimElem animElem, bool forward)
    {
        if (_parentWinManager == null)
        {
            return;
        }

		WindowProxy baseWin = _parentWinManager.GetCurWindow();
        if (baseWin != null && baseWin.win == this)
        {
            if (animElem != null)
            {
                // _parentWinManager.PlayAnimAndHideCurWindow(curWinAnim, false, preWinAnim, false);
                _parentWinManager.PlayAnimAndHideCurWindow(animElem, forward, null, false);
            }
            else
            {
                _parentWinManager.HideCurWindow();
            }
        }
        else
        {
            _parentWinManager.HideWindow((WindowProxy)this.proxy);
        }
    }

    public WindowProxy ShowRootWindow<T>(bool anim = false)
    {
		WindowProxy win = RootWindowManager.instance.ShowWindow<T>();

        if (anim)
        {
			RootWindowManager.instance.PlayAnimAndHidePreWindow(curWinAnim, true, preWinAnim, true);
        }
		return win;
    }

	public WindowProxy ShowWindow<T>(bool anim = false)
    {
		WindowProxy win = _parentWinManager.ShowWindow<T>(!anim);
        if (anim)
        {
			_parentWinManager.PlayAnimAndHidePreWindow(curWinAnim, true, preWinAnim, true);
        }

		return win;
    }

    public WindowProxy ShowChildWindow(System.Type t)
    {
        return ShowChildWindow(t, false);
    }

    public WindowProxy ShowChildWindow(System.Type t, bool anim)
    {
        return ShowChildWindow(t.Name, anim);
    }

    public WindowProxy ShowChildWindow(string winName)
    {
        return ShowChildWindow(winName, false);
    }

    public WindowProxy ShowChildWindow(string winName, bool anim)
    {
        GetPanel();
        WindowProxy win = this.winManager.ShowWindow(winName);

        if (anim)
        {
            this.winManager.PlayAnimAndHidePreWindow(curChildWinAnim, true, preChildWinAnim, true);
        }
        return win;
    }
    public void HideAllChildWindow(bool isDestroy = true, int remainNum = 0)
    {
        this.winManager.HideAllWindow(isDestroy, remainNum);
    }

//	public WindowProxy ShowChildWindow<T>(bool anim)
//    {
//		WindowProxy win = this.winManager.ShowWindow<T>();
//
//        if (anim)
//        {
//			this.winManager.PlayAnimAndHidePreWindow(curChildWinAnim, true, preChildWinAnim, true);
//        }
//		return win;
//    }

//    protected void ShowTips(string tip, float duration = 0f)
//    {
//        tips.SetActive(true);
//        var label = tips.GetComponentInChildren<UILabel>();
//        label.text = tip;
//
//        var tween = tips.GetComponent<UITweener>();
//        if (tween) tween.ResetToBeginning();
//        if (duration > 0)
//        {
//            var twe = TweenAlpha.Begin(tips, duration, 0);
//            twe.AddOnFinished(() => { HideTips(); });
//        }
//    }

//    protected void HideTips()
//    {
//        tips.SetActive(false);
//    }

    public static GameObject CreateBlockClick(GameObject obj, UIPanel panel)
    {
        GameObject blockClick = new GameObject();
        blockClick.name = "blockClick";
        blockClick.AddComponent<BoxCollider2D>();
        UIWidget sprite = blockClick.AddComponent<UIWidget>();
        sprite.gameObject.layer = obj.layer;
        sprite.autoResizeBoxCollider = true;
        sprite.transform.SetParent(panel.transform, false);
        sprite.SetAnchor(panel.gameObject, 0, 0, 0, 0);
        sprite.depth = -100;
        return blockClick;
    }
}
